package jscontrol

import (
	"errors"

	"github.com/dop251/goja"
)

//GetResAndErr 从js返回值json中获取返回值
func GetResAndErr(val goja.Value, runtime *goja.Runtime) (bool, error) {
	objr, err := IsGojaObject(val, runtime)
	if err != nil {
		return false, err
	}
	resjs := objr.Get("res")
	errjs := objr.Get("err")
	if resjs == nil || errjs == nil {
		return false, errors.New("返回值错误")
	}
	if rest, ok := resjs.Export().(bool); ok {
		if errjs.Export() == nil {
			return true, nil
		}
		if errt, ok := errjs.Export().(string); ok {
			return rest, errors.New(errt)
		}
	}
	return false, errors.New("返回值错误")
}

//GetFromResAndErr 从(bool, error)返回一个jsValue
func GetFromResAndErr(res bool, err error, runtime *goja.Runtime) goja.Value {
	object := runtime.NewObject()
	object.Set("res", res)
	if err == nil {
		object.Set("err", nil)
	} else {
		object.Set("err", err.Error())
	}
	return object
}

//IsGojaObject 判断并获取是否是gojaobject对象
func IsGojaObject(value goja.Value, runtime *goja.Runtime) (*goja.Object, error) {
	if value == nil {
		return nil, errors.New("对象初始化失败")
	}
	objr := value.ToObject(runtime)
	if objr == nil {
		return nil, errors.New("对象初始化失败。未能实例化")
	}
	return objr, nil
}

//GetJsFunction 从JS中获得函数
func GetJsFunction(funcName string, content *goja.Object) (goja.Callable, error) {
	fn, res := goja.AssertFunction(content.Get(funcName))
	if res {
		return fn, nil
	}
	return nil, errors.New(funcName + "函数未实现")
}

//GetBufferFromArgument 从参数中获取数组
func GetBufferFromArgument(val goja.Value) ([]uint8, error) {
	p1, err := GetInterfaceFromArgument(val)
	if err != nil {
		return nil, err
	}
	buffer, ok := p1.([]interface{})
	var bytebuffer []uint8
	if ok && buffer != nil {
		for i := 0; i < len(buffer); i++ {
			if value, ok := buffer[i].(uint8); ok {
				bytebuffer[i] = value
			} else {
				return nil, errors.New("参数不是uint8数组")
			}
		}
	} else {
		bytebuffer, ok = p1.([]uint8)
		if !ok || bytebuffer == nil {
			return nil, errors.New("待转换参数不是数组")
		}
	}
	return bytebuffer, nil
}

//GetInt64FromArgument 从参数中获取一个整型
func GetInt64FromArgument(val goja.Value) (int64, error) {
	p1, err := GetInterfaceFromArgument(val)
	if err != nil {
		return 0, err
	}
	res, ok := p1.(int64)
	if ok {
		return res, nil
	}
	return 0, errors.New("参数转换失败")
}

//GetUInt64FromArgument 从参数中获取一个整型
func GetUInt64FromArgument(val goja.Value) (uint64, error) {
	res, err := GetInt64FromArgument(val)
	if err != nil {
		return 0, err
	}
	res2 := uint64(res)
	return res2, nil
}

//GetInterfaceFromArgument 从参数中获取一个整型
func GetInterfaceFromArgument(val goja.Value) (interface{}, error) {
	p1 := val.Export()
	if p1 == nil {
		return 0, errors.New("Send函数调用参数类型错误")
	}
	return p1, nil
}

//GetIntFromArgument 从参数中获取一个整型
func GetIntFromArgument(val goja.Value) (int, error) {
	res, err := GetInt64FromArgument(val)
	if err != nil {
		return 0, err
	}
	intMax := int(^uint(0) >> 1)
	if res > int64(intMax) {
		return 0, errors.New("参数值大于int最大值")
	}
	return int(res), nil
}

//GetStringFromArgument 从参数中获取一个字符串
func GetStringFromArgument(val goja.Value) (string, error) {
	p1, err := GetInterfaceFromArgument(val)
	if err != nil {
		return "", err
	}
	res, ok := p1.(string)
	if ok {
		return res, nil
	}
	return "", errors.New("参数转换失败")
}

//GetBoolFromArgument 从参数中获取一个BOOL
func GetBoolFromArgument(val goja.Value) (bool, error) {
	p1, err := GetInterfaceFromArgument(val)
	if err != nil {
		return false, err
	}
	res, ok := p1.(bool)
	if ok {
		return res, nil
	}
	return false, errors.New("参数转换失败")
}
